﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.TextFormatting;
using System.Windows.Documents;
using System.Windows.Media;
using System.Globalization;
using System.Windows;

namespace SDF.TextFormatting
{
    public class SmartTextRunProperties: TextRunProperties
    {
        #region Constructor

        public SmartTextRunProperties(SmartTextElement element)
        {
            if (element == null)
                throw new ArgumentNullException("source");

            _BackgroundBrush = element.Background; 
            _BaselineAlignment = BaselineAlignment.Baseline;
            _CultureInfo = CultureInfo.CurrentUICulture;
            _FontHintingEmSize = 12.0;
            _FontRenderingEmSize = element.FontSize;
            _ForegroundBrush = element.Foreground;
            _NumberSubstitution = null;
            _TextDecorations = null;
            _TextEffects = element.TextEffects;
            _Typeface = new Typeface(element.FontFamily, element.FontStyle, element.FontWeight, element.FontStretch);
            _TypographyProperties = null;
        }

        public SmartTextRunProperties(SmartInline element)
        {
            if (element == null)
                throw new ArgumentNullException("source");

            _BackgroundBrush = CalculateBackground(element);
            _BaselineAlignment = element.BaselineAlignment;
            _CultureInfo = CultureInfo.CurrentUICulture;
            _FontHintingEmSize = 12.0;
            _FontRenderingEmSize = element.FontSize;
            _ForegroundBrush = element.Foreground;
            _NumberSubstitution = null;
            _TextDecorations = CalculateTextDecorations(element);
            _TextEffects = element.TextEffects;
            _Typeface = new Typeface(element.FontFamily, element.FontStyle, element.FontWeight, element.FontStretch);
            _TypographyProperties = null;
        }

        #endregion

        #region Calculate Methods
        
        // Backgrounds should be "inherited". An <Run> may define no background at all, but if it is a child of a span that does, 
        // then the span background should be applied.
        private Brush CalculateBackground(SmartInline element)
        {
            while (element != null)
            {
                if (element.Background != null)
                    return element.Background;
                element = element.Parent as SmartInline;
            }

            return null;
        }

        // TextDecorations should be "inherited". An <Run> may define no decorations at all, but if it is a child of a span that does, 
        // the the span decorations should be applied.
        private TextDecorationCollection CalculateTextDecorations(SmartInline element)
        {
            var result = new TextDecorationCollection();

            while (element != null)
            {
                result.Add(element.TextDecorations);
                element = element.Parent as SmartInline;
            }

            return result;
        }

        #endregion

        #region Overriden Properties

        public override Brush BackgroundBrush
        {
            get { return _BackgroundBrush; }
        }
        private Brush _BackgroundBrush;

        public override BaselineAlignment BaselineAlignment
        {
            get { return _BaselineAlignment; }
        }
        private BaselineAlignment _BaselineAlignment;

        public override CultureInfo CultureInfo
        {
            get { return _CultureInfo; }
        }
        private CultureInfo _CultureInfo;

        public override double FontHintingEmSize
        {
            get { return _FontHintingEmSize; }
        }
        private double _FontHintingEmSize;

        public override double FontRenderingEmSize
        {
            get { return _FontRenderingEmSize; }
        }
        private double _FontRenderingEmSize;

        public override Brush ForegroundBrush
        {
            get { return _ForegroundBrush; }
        }
        private Brush _ForegroundBrush;

        public override NumberSubstitution NumberSubstitution
        {
            get { return _NumberSubstitution; }
        }
        private NumberSubstitution _NumberSubstitution;

        public override TextDecorationCollection TextDecorations
        {
            get { return _TextDecorations; }
        }
        private TextDecorationCollection _TextDecorations;

        public override TextEffectCollection TextEffects
        {
            get { return _TextEffects; }
        }
        private TextEffectCollection _TextEffects;

        public override Typeface Typeface
        {
            get { return _Typeface; }
        }
        private Typeface _Typeface;

        public override TextRunTypographyProperties TypographyProperties
        {
            get { return _TypographyProperties; }
        }
        private TextRunTypographyProperties _TypographyProperties;

        #endregion
    }
}
